package obecto.core
{
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	
	import mx.core.IStateClient;
	
	import obecto.event.FLEvent;
	import obecto.metadata.MetadataDirectives;
	import obecto.metadata.PartDirective;
	import obecto.utility.MetaUtility;
	import obecto.utility.PartUtility;
	
	[Event(name="initialize", type="obecto.event.FLEvent")]
	[Event(name="creationComplete", type="obecto.event.FLEvent")]
	public class FLUIComponent extends Sprite implements IStateClient, IFLController
	{
		public var asset : Object;
		
		public var view : MovieClip;
		
		public var states : Array;
		
		public var transitions : Array;
		
		public var controller : IFLController;
		
		//****************************************
		// IStateClient implementation:
		//**************************************** 
		private var _currentState : String;
		public function set currentState(value : String) : void
		{
			if (value != null && value != _currentState)
			{
				_currentState = value;
			}
		}
		public function get currentState() : String
		{
			return _currentState;
		}
		
		//****************************************
		// IFLController implementation:
		//**************************************** 
		[Bindable]
		public var component : FLUIComponent;
		
		private var metadata : MetadataDirectives;
		
		public function FLUIComponent()
		{
			// by default the FLUIComponent is also its own controller:
			controller = this;
			
			FLGlobals.topLevelSprite.addEventListener(Event.ENTER_FRAME, handleEnterFrame);
		}
		
		/**
		 * This is an abstract method that gives you the ability to perform certain actions,
		 * when a view part is ready (e.g. adding event listeners):
		 */ 
		virtual protected function partReady(part : DisplayObject, partName : String) : void 
		{
			return;
		}
		
		protected function initialize() : void
		{
			initializeMetadata();
			initializeParts();
			initializeController();
			
			dispatchEvent(new FLEvent(FLEvent.CREATION_COMPLETE));
		} 
		
		protected function initializeMetadata() : void 
		{
			metadata = MetaUtility.resolveMetadata(this);
		}
		
		protected function initializeParts() : void 
		{
			if (view == null && asset != null)
			{
				var assetClass : Class = Class(asset);
				view = MovieClip(new assetClass());
			}
			
			addChild(view);
			
			for each (var directive : PartDirective in metadata.parts)
			{
				var part : DisplayObject = PartUtility.initializePart(this, view, directive);
				partReady(part, directive.name);
			}
		}
		
		protected function initializeController() : void 
		{
			if (controller != this)
			{
				controller.component = this;
			}
		}
		
		protected function handleEnterFrame(e : Event) : void
		{
			FLGlobals.topLevelSprite.removeEventListener(Event.ENTER_FRAME, handleEnterFrame);
			dispatchEvent(new FLEvent(FLEvent.INITIALIZE));
			
			initialize();
		}

	}
}